package com.idlestar.androiddocs.view.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.ListView;

/**
 * 头部可拉伸的ListView。（ImgHeadListView）
 */
public class ElasticListView extends ListView {
    private View mHeader;
    private Animation mHeaderBackAnim;

    private int mHeaderNormalHeight;
    private int mHeaderMaxHeight;

    private int mHeaderReleaseHeight;
    private int mHeaderBackDistanceY;

    public ElasticListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY,
                                   int scrollRangeX, int scrollRangeY,
                                   int maxOverScrollX,
                                   int maxOverScrollY,
                                   boolean isTouchEvent) {
        Log.d("id33", "overScrollBy: deltaY = " + deltaY + ", scrollY = " + scrollY);
        // 一些快速弹动的情况下，不是拉到最上面的时候才引起的“过度下拉”，此时最后一次deltaY后使得
        // header的高度不对，应该在下一次deltaY=0时进行一次调整
        if (deltaY < 0 && getTop() == 0 && getFirstVisiblePosition() == 0) {
            if (mHeader.getHeight() < mHeaderMaxHeight) {
                int newHeight = mHeader.getHeight() - deltaY;
                if (newHeight > mHeaderMaxHeight) {
                    newHeight = mHeaderMaxHeight;
                }
                mHeader.getLayoutParams().height = newHeight;
                mHeader.requestLayout();
            }

        } else if (deltaY > 0 && getTop() == 0 && getFirstVisiblePosition() == 0) {
            // 如果ListView内容不超过一屏幕，下拉后上滑恢复高度的操作在这里
            if (mHeader.getHeight() > mHeaderNormalHeight) {
                int newHeight = mHeader.getHeight() - deltaY;
                if (newHeight < mHeaderNormalHeight) newHeight = mHeaderNormalHeight;
                mHeader.getLayoutParams().height = newHeight;
                mHeader.requestLayout();
            }
        }

        return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,
                scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        int top = mHeader.getTop();
        Log.w("id22", "onScrollChanged: l = " + l + ", t = " + t + ", oldl = " + oldl + ", oldt = "  + oldt);
        if (top < 0 && mHeader.getHeight() > mHeaderNormalHeight && getFirstVisiblePosition() == 0) {
            // 此处是处理过度下拉后继续上推的情况，
            // 执行条件是：header可见，headerHeight比正常高度大
            int newHeight = mHeader.getHeight() + top;

            if (newHeight < mHeaderNormalHeight) {
                newHeight = mHeaderNormalHeight;
            }
            mHeader.getLayoutParams().height = newHeight;
            mHeader.setTop(0);
            mHeader.requestLayout();
        }
    }

    @Override
    public void addHeaderView(View v, Object data, boolean isSelectable) {
        super.addHeaderView(v, data, isSelectable);
        mHeader = v;
        int heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        mHeader.measure(0, heightSpec);
        mHeaderNormalHeight = mHeader.getMeasuredHeight();
        mHeaderMaxHeight = 2 * mHeaderNormalHeight;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case  MotionEvent.ACTION_UP:
                if (mHeader.getTop() == 0 && mHeader.getHeight() > mHeaderNormalHeight) {
                    processBackAnim();
                }
                break;
            case MotionEvent.ACTION_DOWN:
                mHeader.clearAnimation();
                break;
            case MotionEvent.ACTION_MOVE:
                // 如果ListView的item数量不足一屏幕，手指在底下的非item区域滑动时onScrollChanged和overScrollBy都不会执行
                // 或许使用GestureDetector或直接检测onTouchEvent更严格些
                Log.d("id22", "ACTION_MOVE");
                break;
        }
        return super.onTouchEvent(ev);
    }

    private void processBackAnim() {
        Log.d("id33", "processBackAnim");
        mHeaderReleaseHeight = mHeader.getHeight();
        mHeaderBackDistanceY = mHeader.getHeight() - mHeaderNormalHeight;
        if (mHeaderBackAnim == null) {
            mHeaderBackAnim = new Animation() {
                @Override
                protected void applyTransformation(float interpolatedTime, Transformation t) {
                    int newHeight = (int) (mHeaderReleaseHeight - interpolatedTime * mHeaderBackDistanceY);
                    if (newHeight < mHeaderNormalHeight) newHeight = mHeaderNormalHeight;
                    mHeader.getLayoutParams().height = newHeight;
                    mHeader.requestLayout();
                }

            };

            mHeaderBackAnim.setDuration(300);
        }
        mHeader.clearAnimation();
        mHeader.startAnimation(mHeaderBackAnim);
    }
}
